#include <glog/logging.h>
#include <QThread>
#include <QSharedPointer>
#include <QMetaType>

#include "util/utils.h"
#include "util/common_utils.h"

#include "manager/config_manager.h"
#include "manager/calibrate_manager.h"
#include "manager/datakeeper.h"
#include "manager/mqtt_manager.h"

#include "manager/camera_manager.h"
#include "manager/algorithm_manager.h"

#include "manager/mock_manager.h"
#include "manager/timer_manager.h"
#include "detect/result_manager.h"

Q_DECLARE_METATYPE(Mat);
Q_DECLARE_METATYPE(QSharedPointer<Mat>);
Q_DECLARE_METATYPE(std::vector<ObjectEntity>);

void CommonUtils::init_all_instance()
{
    qRegisterMetaType<Mat>("Mat");
    qRegisterMetaType<QSharedPointer<Mat> >("QSharedPointer<Mat>");
    qRegisterMetaType<std::vector<ObjectEntity> >("std::vector<ObjectEntity>");
    LOG(INFO) << "start application" << VERSION_NAME;

    ConfigManager::getInstance();
    ConfigManager::getInstance()->load();

    AppConfig *app_config = ConfigManager::getInstance()->get_app_config();
    ConfigEntity *ecb_config = ConfigManager::getInstance()->get_ecb_config();
    int start_delay = app_config->start_delay;
    LOG(INFO) << "CommonUtils | start delay" << start_delay << "seconds";
    QThread::sleep(start_delay);

    LOG(INFO) << "CommonUtils | allocate all instance";
    CalibrateManager::get_instance();
    DataKeeper::get_instance();
    MqttManager::getInstance();
    MqttObserver::get_instance();
    CameraManager::get_instance();
    AlgorithmManager::get_instance();
    MockManager::get_instance();
    TimerManager::get_instance();
    ResultManager::get_instance();

    LOG(INFO) << "CommonUtils | init all instance";
    QString str_src = ecb_config->target_points;
    QString str_dst = ecb_config->prespective_points;
    std::vector<cv::Point2f> src = Utils::parse_points(str_src);
    std::vector<cv::Point2f> dst = Utils::parse_points(str_dst);
    CalibrateManager::get_instance()->init(&src, &dst);
    MqttManager::getInstance()->init();
    AlgorithmManager::get_instance()->init();
    CameraManager::get_instance()->init();
    ResultManager::get_instance()->init();

    LOG(INFO) << "CommonUtils | start camera and timer";
    CameraManager::get_instance()->start();
    TimerManager::get_instance()->start_all_timer();
}

